﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using ArtMath.Window;
using ArtMath.Setting;
using ArtMath.Flag;
using ArtMath.Component;
using ArtMath.Parameter;
using ArtMath.Animation;
using WeifenLuo.WinFormsUI.Docking;
using ArtMath.Interaction.Interface;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using System.IO;
using ArtMath.Resource;
using System.Text;
using System.Security;
using System.Net;
using ArtMath.CommonType;
using ArtMath.Core.Helper;

namespace ArtMath
{
    public static class Program
    {
        public static MainWindow WinMain;
        public static DocumentsManagerWindow WinDocuments;
        public static ToolsWindow WinTools;
        public static ParametersManagerWindow WinParameters;
        public static ComponentsManagerWindow WinComponents;
        public static PropertyWindow WinProperty;
        public static AnimationsManagerWindow WinAnimations;
        //public static TerminalWindow WinCommand;
        public static RecycleBinWindow WinRecycleBin;
        public static object[] Clipboard;
        public static Base FormatSource;
        public static bool LaunchCancelled;
        public static string[] OpenFiles;
        public static IntPtr AdministratorHandle;
        static readonly object saveLocker = new object();
        const int BufferLength = 2048;
        const string FeedbackPath = Flags.OfficialWebsite + "/" + Flags.SoftwareName + "/Feedback";
        static Program()
        {
            Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(Settings.Instance.Language);
            InputFunctionWindow.LocalizeFunctionName();
        }
        #region Freeze
        public static void FreezeLayer()
        {
            WinComponents.SketchPad_Layer_Activated(null);
        }
        public static void FreezeSketchPad()
        {
            FreezeLayer();
            WinParameters.SketchPad_Activated(null);
            WinTools.SketchPad_Activated(null);
            WinProperty.SketchPad_Activated(null);
            WinAnimations.SketchPad_Activated(null);
            WinMain.SketchPad_Activated(null);
            WinRecycleBin.SketchPad_Activated(null);
        }
        public static void FreezeDocument()
        {
            FreezeSketchPad();
            WinDocuments.Document_Activated(null);
            WinRecycleBin.Document_Activated(null);
            WinMain.Document_Activated(null);
            WinParameters.Document_Activated(null);
        }
        #endregion
        #region RegisterEvents
        public static void RegisterParameterEvents(this BasicParameter p)
        {
            p.Recovered += WinParameters.Parameter_Recovered;
        }
        public static void RegisterAnimationEvents(this AnimationBase ani)
        {
            ani.Recovered += WinAnimations.Animation_Recovered;
        }
        public static void RegisterDocumentEvents(this Document doc)
        {
            doc.Activated += WinRecycleBin.Document_Activated;
            doc.Activated += WinMain.Document_Activated;
            doc.Activated += WinParameters.Document_Activated;
            doc.Activated += WinDocuments.Document_Activated;
            doc.NoSketchPadSelected += FreezeSketchPad;
            doc.TitleChanged += WinDocuments.Document_TitleChanged;
            doc.AddSketchpadButton.Click += WinDocuments.Document_AddSketchpadButton_Click;
            doc.DocumentWindow.FloatAllMenu.Click += WinDocuments.Document_DocumentWindow_FloatAll_Click;
            doc.DocumentWindow.SaveMenu.Click += WinDocuments.Document_DocumentWindow_Save_Click;
            doc.DocumentWindow.CloseMenu.Click += WinDocuments.Document_DocumentWindow_Close_Click;
            doc.DocumentWindow.CloseOtherMenu.Click += WinDocuments.Document_DocumentWindow_CloseOther_Click;
            doc.DocumentWindow.CloseAllMenu.Click += WinDocuments.Document_DocumentWindow_CloseAll_Click;
            doc.DocumentWindow.CloseLeftMenu.Click += WinDocuments.Document_DocumentWindow_CloseLeft_Click;
            doc.DocumentWindow.CloseRightMenu.Click += WinDocuments.Document_DocumentWindow_CloseRight_Click;
            doc.DocumentWindow.DockStateChanged += WinDocuments.lvDocuments_SelectedIndexChanged;
            doc.DocumentWindow.DockStateChanged += WinMain.Document_DocumentWindow_DockStateChanged;
            doc.TitleChanged += doc.DocumentWindow.Document_TitleChanged;
        }
        public static void RegisterPadEvents(this SketchPad pad)
        {
            pad.CurrentCoordinateChanged += WinMain.SketchPad_CurrentCoordinateChanged;
            pad.CoordinateSystemChanged += WinTools.SketchPad_CoordinateChanged;
            pad.NameChanged += WinMain.SketchPad_NameChanged;
            pad.NewCommandAdded += WinMain.SketchPad_NewCommandAdded;
            pad.Redid += WinMain.SketchPad_Redid;
            pad.Undid += WinMain.SketchPad_Undid;
            pad.Layer.RefreshWindowsStatus += WinComponents.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus += WinProperty.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus += WinParameters.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus += WinMain.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus += WinDocuments.SketchPad_Layer_RefreshWindowsStatus;
            pad.Canvas.MouseUp += WinProperty.SketchPad_Canvas_MouseUp;
            pad.ViewPropertyMenuClick += WinProperty.SketchPad_ViewPropertyMenuClick;
            pad.CopyObject += WinComponents.CopyObject;
            pad.PasteObject += WinComponents.PasteObject;
            pad.CopyStyle += WinComponents.CopyStyle;
            pad.PasteStyle += WinComponents.PasteStyle;
            pad.AnimationCreated += WinAnimations.AnimationCreated;
            pad.ToolStripCreated += pad.Document.DocumentWindow.SketchPad_ToolStripCreated;
            pad.RefreshMenuClick += WinProperty.SketchPad_RefreshMenuClick;
            pad.Activated += WinTools.SketchPad_Activated;
            pad.Activated += WinProperty.SketchPad_Activated;
            pad.Activated += WinAnimations.SketchPad_Activated;
            pad.Activated += WinMain.SketchPad_Activated;
            pad.Activated += WinParameters.SketchPad_Activated;
            pad.Activated += WinRecycleBin.SketchPad_Activated;
            pad.ParameterCreated += WinParameters.SketchPad_ParameterCreated;
            pad.Layer.Activated += WinComponents.SketchPad_Layer_Activated;
        }
        #endregion
        #region ReleaseEvents
        public static void ReleaseParameterEvents(this BasicParameter p)
        {
            p.Recovered -= WinParameters.Parameter_Recovered;
        }
        public static void ReleaseAnimationEvents(this AnimationBase ani)
        {
            ani.Recovered -= WinAnimations.Animation_Recovered;
        }
        public static void ReleaseDocumentEvents(this Document doc)
        {
            doc.Activated -= WinRecycleBin.Document_Activated;
            doc.Activated -= WinMain.Document_Activated;
            doc.Activated -= WinParameters.Document_Activated;
            doc.Activated -= WinDocuments.Document_Activated;
            doc.NoSketchPadSelected -= FreezeSketchPad;
            doc.TitleChanged -= WinDocuments.Document_TitleChanged;
            doc.AddSketchpadButton.Click -= WinDocuments.Document_AddSketchpadButton_Click;
            doc.DocumentWindow.FloatAllMenu.Click -= WinDocuments.Document_DocumentWindow_FloatAll_Click;
            doc.DocumentWindow.SaveMenu.Click -= WinDocuments.Document_DocumentWindow_Save_Click;
            doc.DocumentWindow.CloseMenu.Click -= WinDocuments.Document_DocumentWindow_Close_Click;
            doc.DocumentWindow.CloseOtherMenu.Click -= WinDocuments.Document_DocumentWindow_CloseOther_Click;
            doc.DocumentWindow.CloseAllMenu.Click -= WinDocuments.Document_DocumentWindow_CloseAll_Click;
            doc.DocumentWindow.CloseLeftMenu.Click -= WinDocuments.Document_DocumentWindow_CloseLeft_Click;
            doc.DocumentWindow.CloseRightMenu.Click -= WinDocuments.Document_DocumentWindow_CloseRight_Click;
            doc.DocumentWindow.DockStateChanged -= WinDocuments.lvDocuments_SelectedIndexChanged;
            doc.DocumentWindow.DockStateChanged -= WinMain.Document_DocumentWindow_DockStateChanged;
            doc.TitleChanged -= doc.DocumentWindow.Document_TitleChanged;
        }
        public static void ReleasePadEvents(this SketchPad pad)
        {
            pad.CurrentCoordinateChanged -= WinMain.SketchPad_CurrentCoordinateChanged;
            pad.CoordinateSystemChanged -= WinTools.SketchPad_CoordinateChanged;
            pad.NameChanged -= WinMain.SketchPad_NameChanged;
            pad.NewCommandAdded -= WinMain.SketchPad_NewCommandAdded;
            pad.Redid -= WinMain.SketchPad_Redid;
            pad.Undid -= WinMain.SketchPad_Undid;
            pad.Layer.RefreshWindowsStatus -= WinComponents.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus -= WinProperty.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus -= WinParameters.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus -= WinMain.SketchPad_Layer_RefreshWindowsStatus;
            pad.Layer.RefreshWindowsStatus -= WinDocuments.SketchPad_Layer_RefreshWindowsStatus;
            pad.Canvas.MouseUp -= WinProperty.SketchPad_Canvas_MouseUp;
            pad.ViewPropertyMenuClick -= WinProperty.SketchPad_ViewPropertyMenuClick;
            pad.CopyObject -= WinComponents.CopyObject;
            pad.PasteObject -= WinComponents.PasteObject;
            pad.CopyStyle -= WinComponents.CopyStyle;
            pad.PasteStyle -= WinComponents.PasteStyle;
            pad.AnimationCreated -= WinAnimations.AnimationCreated;
            pad.ToolStripCreated -= pad.Document.DocumentWindow.SketchPad_ToolStripCreated;
            pad.RefreshMenuClick -= WinProperty.SketchPad_RefreshMenuClick;
            pad.Activated -= WinTools.SketchPad_Activated;
            pad.Activated -= WinProperty.SketchPad_Activated;
            pad.Activated -= WinAnimations.SketchPad_Activated;
            pad.Activated -= WinMain.SketchPad_Activated;
            pad.Activated -= WinParameters.SketchPad_Activated;
            pad.Activated -= WinRecycleBin.SketchPad_Activated;
            pad.ParameterCreated -= WinParameters.SketchPad_ParameterCreated;
            pad.Layer.Activated -= WinComponents.SketchPad_Layer_Activated;
        }
        #endregion
        public static void BeforeSaving(this Document doc)
        {
            lock (saveLocker)
            {
                foreach (SketchPad pad in doc.Pads)
                {
                    foreach (AnimationBase ani in pad.Animations)
                    {
                        ani.ReleaseAnimationEvents();
                    }
                    pad.ReleasePadEvents();
                }
                foreach (BasicParameter param in doc.Parameters)
                {
                    param.ReleaseParameterEvents();
                }
                doc.ReleaseDocumentEvents();
            }
        }
        public static bool SilentSave(this Document doc, FileStream stream)
        {
            bool res;
            doc.BeforeSaving();
            res = doc.Save(stream, Document.SaveReason.AutoSave);
            doc.AfterSaved();
            if (res)
            {
                if (doc.LinkedFile == null)
                {
                    string key = doc.GetHashCode().ToString();
                    if (UserOptions.Instance.AutoSaveNewestPath.ContainsKey(key))
                    {
                        UserOptions.Instance.AutoSaveNewestPath[key] = stream.Name;
                    }
                    else
                    {
                        UserOptions.Instance.AutoSaveNewestPath.Add(key, stream.Name);
                    }
                }
                else
                {
                    if (UserOptions.Instance.AutoSaveNewestPath.ContainsKey(doc.LinkedFile.Name))
                    {
                        UserOptions.Instance.AutoSaveNewestPath[doc.LinkedFile.Name] = stream.Name;
                    }
                    else
                    {
                        UserOptions.Instance.AutoSaveNewestPath.Add(doc.LinkedFile.Name, stream.Name);
                    }
                }
                UserOptions.Instance.Save();
            }
            return res;
        }
        public static void AfterSaved(this Document doc)
        {
            lock (saveLocker)
            {
                doc.RegisterDocumentEvents();
                foreach (BasicParameter param in doc.Parameters)
                {
                    param.RegisterParameterEvents();
                }
                foreach (SketchPad pad in doc.Pads)
                {
                    pad.RegisterPadEvents();
                    foreach (AnimationBase ani in pad.Animations)
                    {
                        ani.RegisterAnimationEvents();
                    }
                }
            }
        }
        //语言热切换有BUG
        //public static void SwitchLanguage(string lang)
        //{
        //    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);
        //    applyResources(WinMain, WinDocuments, WinTools, WinParameters, WinComponents, WinProperty, WinAnimations);
        //    InputFunctionWindow.LocalizeFunctionName();
        //}
        //static void applyResources(params Form[] forms)
        //{
        //    WinMain.Hide();
        //    foreach (Form frm in forms)
        //    {
        //        if (frm == null) continue;
        //        foreach (Control ctl in frm.Controls)
        //        {
        //            ctl.SuspendLayout();
        //        }
        //        frm.SuspendLayout();
        //        Type winType = frm.GetType();
        //        ComponentResourceManager resources = new ComponentResourceManager(winType);
        //        FieldInfo[] fis = winType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        //        foreach (FieldInfo field in fis)
        //        {
        //            Component comp = field.GetValue(frm) as Component;
        //            if (comp == null) continue;
        //            resources.ApplyResources(comp, field.Name);
        //        }
        //        resources.ApplyResources(frm, "$this");
        //        foreach (Control ctl in frm.Controls)
        //        {
        //            ctl.ResumeLayout(false);
        //            ctl.PerformLayout();
        //        }
        //        frm.ResumeLayout(false);
        //        frm.PerformLayout();
        //        ISwitchLanguage isl = frm as ISwitchLanguage;
        //        if (isl != null)
        //        {
        //            isl.CustomSwitchLanguage();
        //        }
        //    }
        //    WinMain.Show();
        //}
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            OpenFiles = args;
            using (Mutex mtx = new Mutex(true, Application.ProductName, out bool createNew))
            {
                if (createNew)
                {
                    //Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                    //Application.ThreadException += Application_ThreadException;
                    //AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    SplashScreenWindow splash = new SplashScreenWindow();
                    Application.Run(splash);
                    if (!LaunchCancelled)
                    {
                        //生成窗口
                        WinDocuments = new DocumentsManagerWindow();
                        WinParameters = new ParametersManagerWindow();
                        UIInteraction.ObjectArguments = WinTools = new ToolsWindow(splash.ToolsWindowData);
                        WinAnimations = new AnimationsManagerWindow();
                        WinComponents = new ComponentsManagerWindow();
                        WinProperty = new PropertyWindow();
                        //WinCommand = new TerminalWindow();
                        UIInteraction.RecycleBin = WinRecycleBin = new RecycleBinWindow();
                        UIInteraction.StatusMessage = WinMain = new MainWindow(splash.MainWindowData);//主窗口必须在子窗口之后初始化
                        UIInteraction.Rename = new Renamer();
                        UIInteraction.PickComponent = new ComponentPicker();
                        UIInteraction.CorrectCoordinate = new CoordinateCorrector();
                        //
                        Flags.EnableHotKey();
                        Application.Run(WinMain);
                        Flags.DisableHotKey();
                        Settings.Instance.Save();
                        UserOptions.Instance.Save();
                    }
                }
                else
                {
                    showRunningInstance(getRunningInstance());
                }
            }
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            handleException(e.ExceptionObject as Exception);
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
        {
            handleException(e.Exception);
        }

        static void handleException(Exception ex)
        {
            if (ex is UnauthorizedAccessException || ex is SecurityException)
            {
                MessageBox.Show(Resources.Translate("PermissionDenied") + Environment.NewLine + ex.Message, Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else
            {
                DialogResult res = MessageBox.Show(string.Format(Resources.Translate("UnhandledExceptionPrompt"), Environment.NewLine), Resources.Translate("Ask"), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                switch (res)
                {
                    case DialogResult.Cancel:
                        Environment.Exit(-1);
                        break;
                    case DialogResult.No:
                        StringBuilder sb = new StringBuilder();
                        sb.AppendLine("Basic Information:");
                        sb.AppendLine("DateTime: " + DateTime.Now);
                        sb.AppendLine($"OS: {Environment.OSVersion.Platform} ({(Environment.Is64BitOperatingSystem ? "64bit" : "32bit")})");
                        sb.AppendLine("OS Version: " + Environment.OSVersion.VersionString);
                        sb.AppendLine("Processor Count: " + Environment.ProcessorCount);
                        sb.AppendLine("Primary Monitor Resolution: " + SystemInformation.PrimaryMonitorSize);
                        sb.AppendLine("Executable Path: " + Application.ExecutablePath);
                        sb.AppendLine();
                        sb.AppendLine("Exception Information:");
                        sb.AppendLine("Message: " + ex.Message);
                        sb.AppendLine("Source: " + ex.Source);
                        sb.AppendLine("StackTrace: " + ex.StackTrace);
                        try
                        {
                            WebClient wc = new WebClient();
                            string credPath = Path.Combine(Flags.TempPath, Guid.NewGuid().ToString());
                            wc.DownloadFile(FeedbackPath + "/credential", credPath);
                            string[] lns = File.ReadAllLines(credPath);
                            string logPath = Path.Combine(Flags.TempPath, Guid.NewGuid().ToString());
                            File.WriteAllText(logPath, sb.ToString());
                            FileInfo fi = new FileInfo(logPath);
                            FtpWebRequest req = WebRequest.Create($"ftp://{Flags.OfficialIP}:21/" + fi.Name + ".log") as FtpWebRequest;
                            req.UseBinary = true;
                            req.Credentials = new NetworkCredential(lns[0], lns[1]);
                            req.KeepAlive = req.UsePassive = false;
                            req.Method = WebRequestMethods.Ftp.UploadFile;
                            req.ContentLength = fi.Length;
                            req.Proxy = null;
                            byte[] buff = new byte[BufferLength];
                            FileStream fs = fi.OpenRead();
                            int contentlen;
                            Stream stream = req.GetRequestStream();
                            while ((contentlen = fs.Read(buff, 0, BufferLength)) != 0)
                            {
                                stream.Write(buff, 0, contentlen);
                            }
                            stream.Close();
                            fs.Close();
                            File.Delete(logPath);
                        }
                        catch (Exception ex2)
                        {
                            MessageBox.Show(ex2.Message, Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                        Environment.Exit(-1);
                        break;
                }
            }
        }
        public static IDockContent GetContentFromPersistString(string persistString)
        {
            if (persistString == typeof(DocumentsManagerWindow).FullName)
            {
                return WinDocuments;
            }
            else if (persistString == typeof(ToolsWindow).FullName)
            {
                return WinTools;
            }
            else if (persistString == typeof(ParametersManagerWindow).FullName)
            {
                return WinParameters;
            }
            else if (persistString == typeof(ComponentsManagerWindow).FullName)
            {
                return WinComponents;
            }
            else if (persistString == typeof(PropertyWindow).FullName)
            {
                return WinProperty;
            }
            else if (persistString == typeof(AnimationsManagerWindow).FullName)
            {
                return WinAnimations;
            }
            //else if (persistString == typeof(TerminalWindow).FullName)
            //{
            //    return WinCommand;
            //}
            //else if (persistString == typeof(RecycleBinWindow).FullName)
            //{
            //    return WinRecycleBin;
            //}
            else
            {
                return null;
            }
        }
        public static void LoadDefaultLayout(DockPanel dp)
        {
            dp.DockLeftPortion = 260;
            dp.DockRightPortion = dp.Parent.Width * 0.15;
            //左侧窗口
            WinDocuments.Show(dp, DockState.DockLeft);
            WinTools.Show(WinDocuments.Pane, DockAlignment.Bottom,
                Settings.Instance.WinToolsHeight / (Settings.Instance.WinDocumentsHeight + Settings.Instance.WinToolsHeight + Settings.Instance.WinParametersHeight));
            WinParameters.Show(WinDocuments.Pane, DockAlignment.Bottom,
                Settings.Instance.WinParametersHeight / (Settings.Instance.WinParametersHeight + Settings.Instance.WinDocumentsHeight));
            //右侧窗口
            WinAnimations.Show(dp, DockState.DockRight);
            WinProperty.Show(WinAnimations.Pane, DockAlignment.Bottom,
                Settings.Instance.WinPropertiesHeight / (Settings.Instance.WinAnimationsHeight + Settings.Instance.WinComponentsHeight + Settings.Instance.WinPropertiesHeight));
            WinComponents.Show(WinAnimations.Pane, DockAlignment.Bottom,
                Settings.Instance.WinComponentsHeight / (Settings.Instance.WinComponentsHeight + Settings.Instance.WinAnimationsHeight));
            //WinCommand.Show(dp, DockState.DockBottomAutoHide);
        }
        //private const int SW_HIDE = 0, SW_NORMAL = 1, SW_MAXIMIZE = 3, SW_SHOWNOACTIVATE = 4, SW_SHOW = 5, 
        //    SW_MINIMIZE = 6, SW_RESTORE = 9, SW_SHOWDEFAULT = 10;
        static void showRunningInstance(Process instance)
        {
            Utility.ShowWindowAsync(instance.MainWindowHandle, 9);//显示
            Utility.SetForegroundWindow(instance.MainWindowHandle);//当到最前端
        }
        static Process getRunningInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
            //遍历与当前进程名称相同的进程列表 
            foreach (Process item in processes)
            {
                //忽略同一个进程 
                if (item.Id == current.Id) continue;
                //保证要打开的进程同已经存在的进程来自同一文件路径
                if (item.MainModule.FileName == current.MainModule.FileName)
                {
                    return item;
                }
            }
            return null;
        }
        public static class ProcessEx
        {
            private static class NativeMethods
            {
                internal const uint GW_OWNER = 4;

                internal delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

                [DllImport("User32.dll", CharSet = CharSet.Auto)]
                internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

                [DllImport("User32.dll", CharSet = CharSet.Auto)]
                internal static extern int GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);

                [DllImport("User32.dll", CharSet = CharSet.Auto)]
                internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

                [DllImport("User32.dll", CharSet = CharSet.Auto)]
                internal static extern bool IsWindowVisible(IntPtr hWnd);
            }

            public static IntPtr GetMainWindowHandle(int processId)
            {
                IntPtr MainWindowHandle = IntPtr.Zero;

                NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc((hWnd, lParam) =>
                {
                    IntPtr PID;
                    NativeMethods.GetWindowThreadProcessId(hWnd, out PID);

                    if (PID == lParam &&
                        NativeMethods.IsWindowVisible(hWnd) &&
                        NativeMethods.GetWindow(hWnd, NativeMethods.GW_OWNER) == IntPtr.Zero)
                    {
                        MainWindowHandle = hWnd;
                        return false;
                    }

                    return true;

                }), new IntPtr(processId));

                return MainWindowHandle;
            }
        }
        public static void DoAdmin(MessageContent msg)
        {
            Process admin = Utility.GetProcess($"{Flags.SoftwareName}.Administrator");
            if (admin == null)
            {
                MessageBox.Show("nnn", Resources.Translate("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            msg.dwData = new IntPtr(250);
            byte[] b = Encoding.Default.GetBytes("SHADIU");
            msg.cbData = b.Length + 1;
            msg.lpData = "SHADIU";
            //MessageBox.Show("GLY:"+AdministratorHandle);
            Utility.SendMessage(new IntPtr(5835070), Flags.WM_COPYDATA, IntPtr.Zero, ref msg);
        }
        class Renamer : IRename
        {
            RenameWindow rn;
            public string NewName
            {
                get { return rn.NewName; }
            }
            public DialogResult Rename(string initName, Predicate<string> checkExist, Func<string, string> promptMsg)
            {
                rn = new RenameWindow(initName, checkExist, promptMsg);
                return rn.ShowDialog();
            }
        }
        class ComponentPicker : IPickComponents
        {
            ComponentsPickerWindow cp;
            public DialogResult PickComponents(ListViewItem[] items, int count, string desc, string[] colNames)
            {
                cp = new ComponentsPickerWindow(items, count, desc, colNames);
                return cp.ShowDialog();
            }
        }
        class CoordinateCorrector : ICorrectCoordinate
        {
            CorrectCoordinateWindow ccw;
            public LineBase SelectedLine
            {
                get { return ccw.SelectedLine; }
            }

            public PointBase SelectedPoint
            {
                get { return ccw.SelectedPoint; }
            }

            public DialogResult CorrectCoordinate(string pointName, PointD originCoordinate, ListViewItem[] items)
            {
                ccw = new CorrectCoordinateWindow(pointName, originCoordinate, items);
                return ccw.ShowDialog();
            }
        }
    }
}
